/*
 * Copyright (c) China Telecom Cloud Technology Co., Ltd. 2024-2025. All rights reserved.
 */
#ifndef CONFIGLOADER_H
#define CONFIGLOADER_H

#include <mutex>
#include <vector>
#include <cctype>
#include <memory>
#include <string>
#include <cstdint>
#include <fstream>
#include <cstdlib>
#include <stdexcept>
#include <algorithm>
#include <unordered_map>


//! 配置文件加载器
class ConfigLoader {
public:
    // 定义配置项的名字(配置文件名"config.ini")
    struct EnvVars {
        // TODO(yangxianpku: 2025.08.21): 去掉冗余的const
        static constexpr const char *MEMPOOL_SIZE = "MEMPOOL_SIZE";  // 内存池大小
        static constexpr const char *MOUNT_POINT  = "MOUNT_POINT";   // KV Cache存储根路径
        static constexpr const char *BLOCK_SIZE   = "BLOCK_SIZE";    // KV Cache块大小
        static constexpr const char *GET_THREADS  = "GET_THREADS";   // KV Cache读取线程数
        static constexpr const char *PUT_THREADS  = "PUT_THREADS";   // KV Cache写入线程数
        static constexpr const char *LOG_PATH     = "LOG_PATH";      // 日志持久化路径
        static constexpr const char *LOG_LEVEL    = "LOG_LEVEL";     // 日志级别
        static constexpr const char *CLIENT_PORT  = "CLIENT_PORT";   // gRPC服务端口
        static constexpr const char *LAYOUT       = "LAYOUT";        // KV Cache FMT
    };

    /**
     *! @brief 获取某个配置项的值(先尝试从配置文件获取，再尝试从环境变量获取)
     * 
     * @tparam T             特定环境变量值的类型
     * @param env_var        环境变量的名字
     * @param cmake_default  该环境变量的默认值
     * @return T  获取环境变量的值，环境变量不存在则返回默认值
     */
    template <typename T>
    static T get_config(const char *env_var, 
                    const T &cmake_default);

private:
    // 去掉字符串两端的空格
    static std::string trim(const std::string &str);

    // 处理某行字符串内容, 读取其中的内容为配置项
    static void process_config_line(const std::string &line, 
            std::unordered_map<std::string, std::string> &map);

    // 获取完整的配置字典
    static const std::unordered_map<std::string, 
                std::string> &get_config_map();
};




template <>
inline int ConfigLoader::get_config<int>(const char *env_var, 
                                const int &cmake_default) {
    const auto &config_map = get_config_map();
    auto it = config_map.find(env_var);
    if (it != config_map.end()) {
        try {
            return std::stoi(it->second);
        } catch (...) {  //! 捕获所有异常
            //! 向上层调用者抛出异常, 如果上层没有catch，则程序运行结束
            throw std::runtime_error("Invalid integer value in config" 
                                " file for: " + std::string(env_var));
        }
    }

    if (const char *env_val = std::getenv(env_var)) {
        try {
            return std::stoi(env_val);
        } catch (...) {
            throw std::runtime_error("Invalid integer value in "
                    "environment for: " + std::string(env_var));
        }
    }

    return cmake_default;
}




template <>
inline uint64_t ConfigLoader::get_config<uint64_t>(const char *env_var, 
                                    const uint64_t &cmake_default) {
    const auto &config_map = get_config_map();
    auto it = config_map.find(env_var);
    if (it != config_map.end()) {
        try {
            return std::stoull(it->second);
        } catch (...) {
            throw std::runtime_error("Invalid uint64 value in config "
                                "file for: " + std::string(env_var));
        }
    }

    if (const char *env_val = std::getenv(env_var)) {
        try {
            return std::stoull(env_val);
        } catch (...) {
            throw std::runtime_error("Invalid uint64 value in "
                    "environment for: " + std::string(env_var));
        }
    }

    return cmake_default;
}




template <>
inline std::string ConfigLoader::get_config<std::string>(const char *env_var, 
                                        const std::string &cmake_default) {
    const auto &config_map = get_config_map();
    auto it = config_map.find(env_var);
    if (it != config_map.end()) {
        return it->second;
    }

    if (const char *env_val = std::getenv(env_var)) {
        return env_val;
    }

    return cmake_default;
}

#endif